#define _GNU_SOURCE
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
#include <grp.h>
#include <pwd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <signal.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <sys/mman.h>

#define ARGS_CHECK(argc,num) {if(argc!=num) {printf("error args\n");return -1;}}
#define ERROR_CHECK(ret,retval,func_name) {if(ret==retval) {perror(func_name);return -1;}}
#define THREAD_ERR_CHECK(ret,func_name) {if(ret!=0) {printf("%s failed,%d %s\n",func_name,ret,strerror(ret));return -1;}}
#define SELFFUNC_ERR_CHECK(ret,func_name) {if(ret!=0) {printf("%s failed\n",func_name);return -1;}}

#define FILENAME "file"

// 文件下载内容结构体
typedef struct 
{
    int data_len;
    char buf[1000];
} train_t;

// 子进程结构体
typedef struct 
{
    pid_t pid; // 子进程id
    int fd; // 与子进程通信的管道
    short busy; // 子进程是否忙碌
} process_data_t;

// child.c 实现

// 创建多个子进程
int make_child(process_data_t *p_manage, int process_num);

// 子进程代码
int child_handle(int fd);

// tcp_epoll_init.c 实现

// 初始化socket
int tcp_init(int* socket_fd,char* ip,char* port);

// 使用epoll监控可用的fd
int epoll_add(int epfd,int fd);

// 发送描述符
int send_fd(int sfd,int fd);

// 接收描述符
int recv_fd(int sfd,int *fd);

// trains_file.c 实现

// 发送文件内容
int train_file(int new_fd);


// 循环接收，显示进度条
int recv_n_show(int sfd, void* buf, int data_len);

// 循环接收，实现大文件接收
int recv_n(int sfd, void* buf, int data_len);

// 循环发送，实现大文件发送
int send_n(int sfd, void* buf, int data_len);